/**
 * @author Andrey Anisimov <hercules@inbox.ru>
 */

import core.effect.AbstractEffect;
import core.util.Timer;

class TimerEffect extends AbstractEffect {

    /**
     * @param duration {int} Effect duration, in milliseconds.
     * @param timer {Timer} Effect timer.
     * @param delay {int} Effect delay.
     * @constructor
     */
    this.TimerEffect = function (duration, timer, delay) {
        super();
        this.duration = duration;
        this.timer = timer;
        this.timer.addTimerListener(this);
        this.time = 0;
        var self = this;
        this.starter = new Timer(delay || 0);
        this.starter.addTimerListener({
            onTimer:function(timer) {
                timer.stop();
                self.started();
            }
        })
    };

    /**
     * @return {Number}
     */
    this.getDelay = function() {
        return this.starter.getInterval();
    };

    /**
     * @param delay {Number}
     */
    this.setDelay = function(delay) {
        this.starter.setInterval(delay);
    };

    /**
     * Sets the effect duration, in milliseconds.
     *
     * @param duration {int} Effect duration, in milliseconds.
     */
    this.setDuration = function (duration) {
        this.duration = duration;
    };

    /**
     * Returns the effect diration, in milliseconds.
     *
     * @return int
     */
    this.getDuration = function () {
        return this.duration;
    };

    /**
     * Sets the timer for the effect.
     *
     * @param timer {Timer} Effect timer.
     */
    this.setTimer = function (timer) {
        this.timer = timer;
    };

    /**
     * @return Timer
     */
    this.getTimer = function () {
        return this.timer;
    };

    /**
     * Returns the elapsed time.
     *
     * @return int
     */
    this.getTime = function () {
        return this.time;
    };

    /**
     * Starts playback.
     *
     * @param time {int} (optional) effect time in milliseconds
     */
    this.play = function(time) {
        if ((TimerEffect.STATE_STARTED === this.state) || (TimerEffect.STATE_PAUSED === this.state)) {
            return;
        }
        this.time = time || 0;
        this.starter.start();
        this.state = TimerEffect.STATE_STARTED;
    };

    /**
     * Stops effect playback.
     */
    this.stop = function () {
        this.timer.stop();
        this.state = TimerEffect.STATE_STOPPED;
        delete this.startTime;
        this.fireStopped();
    };

    /**
     * Pauses effect playback.
     */
    this.pause = function () {
        if (this.state !== TimerEffect.STATE_STARTED) {
            return;
        }
        this.state = TimerEffect.STATE_PAUSED;
        this.timer.pause();
        this.firePaused();
    };

    /**
     * Pauses effect playback.
     */
    this.resume = function () {
        if (TimerEffect.STATE_PAUSED !== this.state) {
            return;
        }
        this.state = TimerEffect.STATE_STARTED;
        this.timer.resume();
        this.startTime = Date.now();
        this.fireResumed();
    };

    /**
     * Checks whether the effect is playing.
     *
     * @return Boolean
     */
    this.isPlaying = function () {
        return (TimerEffect.STATE_STARTED === this.state);
    };

    /**
     * Calls on timer.
     */
    this.onTimer = function () {
        if (TimerEffect.STATE_PAUSED !== this.state) {
            var now = Date.now();
            this.time += (now - this.startTime);
            this.startTime = now;
            if (this.time > this.duration) {
                this.timer.stop();
                this.state = TimerEffect.STATE_FINISHED;
                this.fireFinished();
            } else {
                this.playback();
            }
        }
    };

    /**
     * @protected
     * Performs effect playback on each timer iteration.
     */
    this.playback = function () {
        // Abstract
    };

    /**
     * @protected
     */
    this.started = function() {
        this.fireStarted();
        this.timer.start();
        this.startTime = Date.now();
    };
}

TimerEffect.STATE_READY = 1;
TimerEffect.STATE_STARTED = 2;
TimerEffect.STATE_PAUSED = 3;
TimerEffect.STATE_STOPPED = 4;
TimerEffect.STATE_FINISHED = 5;